#include<bits/stdc++.h>
#define int long long 
#define lson (rt<<1)
#define rson (lson|1)
using namespace std;

int read(){
    int x=0,f=1;
    char c=getchar();
    while(c>'9'||c<'0'){
        if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9'){
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}

const int N=1e5+10;
struct seg{
    int l,r;
    bool f;
    int maxn,minn;
}tree[4*N*10];
int n,m,L,V;
int d,v,a;
int p[N],loc[N*10];
bool f[N*10],flag[N];
pair<int,int>ans[N];
pair<int,int>num[N];

bool cmp(pair<int,int>X,pair<int,int>Y){
    if(X.first!=Y.first) return X.first<Y.first;
    return X.second>Y.second;
}
void build_tree(int l,int r,int rt){
    tree[rt].l=l;
    tree[rt].r=r;
    tree[rt].maxn=-1;
    tree[rt].minn=m+1;
    if(l==r){
        tree[rt].f=f[l];
        if(f[l]) tree[rt].maxn=tree[rt].minn=loc[l];
        return ;
    }
    build_tree(l,((l+r)>>1),lson);
    build_tree(((l+r)>>1)+1,r,rson);
    tree[rt].f=tree[lson].f|tree[rson].f;
    tree[rt].maxn=max(tree[rson].maxn,tree[lson].maxn);
    tree[rt].minn=min(tree[lson].minn,tree[rson].minn);
    return ;
}
bool query_tree(int l,int r,int rt){
    if(tree[rt].l>r||tree[rt].r<l) return 0;
    if(tree[rt].l>=l&&tree[rt].r<=r) return tree[rt].f;
    return query_tree(l,r,lson)|query_tree(l,r,rson);
}
pair<int,int>query_tree_the(int l,int r,int rt){
    if(tree[rt].l>r||tree[rt].r<l) return make_pair(m+1,-1);
    if(tree[rt].l>=l&&tree[rt].r<=r) return make_pair(tree[rt].minn,tree[rt].maxn);
    pair<int,int>k1=query_tree_the(l,r,lson);
    pair<int,int>k2=query_tree_the(l,r,rson);
    return make_pair(min(k1.first,k2.first),max(k1.second,k2.second));
}

signed main(){
    freopen("detect.in","r",stdin);
    freopen("detect.out","w",stdout);
    int _;_=read();
    while(_--){
        n=read();m=read();L=read();V=read();
        for(int i=1;i<=n;i++){
            d=read();v=read();a=read();
            if(a==0){
                if(v>V){num[i]=make_pair(d,L);}
                else{num[i]=make_pair(-1,-1);}
            }else{
                if(a<0){
                    if(v<=V){num[i]=make_pair(-1,-1);}
                    else{
                        double k=(V*V-v*v)*1.0/(2.0*a);
                        k=floor(k-0.000000000001);
                        int XX=(int)k;
                        num[i]=make_pair(d,min(d+XX,L));
                    }
                }else{
                    if(v>V){num[i]=make_pair(d,L);}
                    else{
                        double k=(V*V-v*v)*1.0/(2.0*a);
                        int XX=ceil(k+0.000000000001);
                        if(d+XX>L) num[i]=make_pair(-1,-1);
                        else num[i]=make_pair(d+XX,L);
                    }
                }
            }
        }
        for(int i=1;i<=m;i++){p[i]=read();f[p[i]]=1;}
        sort(p+1,p+1+m);for(int i=1;i<=m;i++) loc[p[i]]=i;
        build_tree(0,L,1);
        int cnt=0;
        for(int i=1;i<=n;i++){
            if(num[i].first==-1&&num[i].second==-1){
                flag[i]=0;
                continue ;
            }
            flag[i]=query_tree(num[i].first,num[i].second,1);
            if(flag[i]){
                pair<int,int>k=query_tree_the(num[i].first,num[i].second,1);
                cnt++;
                ans[cnt]=k;
            }
        }
        cout<<cnt<<" ";
        sort(ans+1,ans+1+cnt,cmp);
        int s=0;
        for(int i=1;i<=cnt;i++){
            int l=ans[i].first,r=ans[i].second;
            int j=i;
            while(ans[j].first<=r&&j<=cnt) j++;
            j--;
            s++;
            i=j;
        }
        cout<<m-s<<endl;
        for(int i=0;i<=L;i++) f[i]=0,loc[p[i]]=-1;
    }
    return 0;
}